package com.jd.orm.framework.core.transaction;

import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;

import com.jd.orm.framework.core.exception.DbError;
import com.jd.orm.framework.core.exception.SystemException;

/**
 * 
 * ClassName: JdbcSession <br/>
 * Function: TODO ADD FUNCTION. <br/>
 * Reason: TODO ADD REASON. <br/>
 * date: 2014-5-13 上午9:24:33 <br/>
 * 
 * @author liubing1@jd.com
 * @version
 * @since up JDK 1.5
 */
public class JdbcSession {

	protected final DataSource dataSource;

	protected Connection connection;

	protected boolean txActive;

	protected TransactionDefinition definition;
		
	public JdbcSession(DataSource dataSource) {
		this.dataSource = dataSource;
		txActive = false;
	}

	public void closeSession() throws Exception {
		if (connection != null) {
			if (txActive == true) {
				throw new Exception(
						"TX was not closed before closing the session");
			}
			try {
				connection.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			connection = null;

		}
	}

	public Connection getConnection() throws Exception {
		if (connection == null) {
			try {
				connection = dataSource.getConnection();
				txActive = false;
				connection.setAutoCommit(false);
			} catch (SQLException sex) {
				throw new Exception("Failed to open non-TX connection", sex);
			}
		}
		return connection;
	}

	public boolean isTransactionActive() {
		return txActive;
	}

	public void beginTransaction(TransactionDefinition definition) {
		this.definition = definition;
		openTx();
	}

	public void commitTransaction() {
		try {
			connection.commit();
		} catch (SQLException sex) {
			throw SystemException.unchecked(sex, DbError.IO_ERROR);
		} finally {
			closeTx();
		}
	}

	public void rollbackTransaction() {
		try {
			connection.rollback();
		} catch (SQLException sex) {
			throw SystemException.unchecked(sex, DbError.TRANSACTION_ERROR);
		} finally {
			closeTx();
		}
	}

	protected void openTx() {
		try {
			if (connection == null) {
				connection = dataSource.getConnection();
			}
			txActive = true;
			connection.setAutoCommit(false);
			if (definition.getIsolationLevel().value() != TransactionDefinition.ISOLATION_DEFAULT) {
				connection.setTransactionIsolation(definition
						.getIsolationLevel().value());
			}
			connection.setReadOnly(definition.isReadOnly());
		} catch (SQLException sex) {
			throw SystemException.unchecked(sex, DbError.IO_ERROR);
		}
	}

	protected void closeTx() {
		txActive = false;
		try {
			connection.setAutoCommit(true);
			// connection.close();
			// connection=null;
		} catch (SQLException sex) {
			throw SystemException.unchecked(sex, DbError.IO_ERROR);
		}
	}
}
